<template>
  <div class="app-container">

    <el-row :gutter="20">
      <el-col :span="4">
        <el-card>
          <el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;" />
          <el-tree
            ref="tree"
            :data="treeData"
            :props="defaultProps"
            show-checkbox
            :filter-node-method="filterNode"
            class="filter-tree"
            :expand-on-click-node=false
            node-key="id"
            @node-click="treeNodeClick"
            @check="treeCheck"
          />
        </el-card>
      </el-col>

      <el-col :span="20">
        <el-table
        ref="table"
        :data="tableData"
        border
        @select="tableSelect"
        @select-all="tableSelectAll"
        @selection-change="tableSelectionChange"
        >
        <el-table-column
          type="selection"
          width="55">
        </el-table-column>
        <el-table-column
          prop="caseNo"
          label="用例编号"
          width="180">
        </el-table-column>
        <el-table-column
          prop="caseDomain"
          label="功能域"
          width="180">
        </el-table-column>
        <el-table-column
          prop="caseModule"
          label="模块">
        </el-table-column>
        <el-table-column
          prop="secondModule"
          label="二级模块">
        </el-table-column>
      </el-table>
      </el-col>
    </el-row>
  </div>
</template>

<script>
export default {

  data() {
    return {
      filterText: '',
      treeData: [{
        id: 1,
        label: '电话',
        type: 'caseDomain',
        children: [{
          id: 4,
          label: '电话本',
          pLabel: '电话',
          type: 'caseModule',
          children: [{
            id: 9,
            type: 'secondModule',
            gLabel: '电话',
            label: '打电话'
          }, {
            id: 10,
            type: 'secondModule',
            gLabel: '电话',
            label: '接电话'
          }]
        }]
      }],
      treeChecked: [],
      cachedDomain: new Set(),
      tableData: [{
        caseNo: 'T0001',
        caseUuid: 'caseUuid1',
        caseDomain: '电话',
        caseModule: '电话本',
        secondModule: '打电话'
      },
      {
        caseNo: 'T0002',
        caseUuid: 'caseUuid2',
        caseDomain: '电话',
        caseModule: '电话本',
        secondModule: '打电话'
      },
      {
        caseNo: 'T0003',
        caseUuid: 'caseUuid3',
        caseDomain: '电话',
        caseModule: '电话本',
        secondModule: '接电话'
      },
      {
        caseNo: 'T0004',
        caseUuid: 'caseUuid4',
        caseDomain: '电话',
        caseModule: '电话本',
        secondModule: '接电话'
      }],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    }
  },
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val)
    },
    treeChecked(newValue, oldValue) {
      console.log(newValue)
      this.updateTableCheck(newValue)
    },
    tableData(newValue, oldValue) {
      console.log(newValue)
    }
  },

  methods: {
    updateTableCheck(treeChecked) {
      for(const row of this.tableData){
        if(treeChecked.indexOf(row.caseUuid) > -1){
          this.$refs.table.toggleRowSelection(row, true);
        }else{
          this.$refs.table.toggleRowSelection(row, false);
        }
      }
    },
    filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    treeNodeClick(data) {
      if(data.type === 'caseDomain' && !this.cachedDomain.has(data.label)){
        this.cachedDomain.add(data.label)
        this.updateLeafNode({
          caseDomainList: this.tableData
        })
      }
    },
    treeCheck(data, treeChecked) {
      // console.log(data, treeChecked)
      let domainName = ''
      switch(data.type){
        case 'caseDomain':
          domainName = data.label
        break;
        case 'caseModule':
          domainName = data.pLabel
        break;
        case 'secondModule':
          domainName = data.gLabel
        break;
        default:
        break;
      }
      if(!this.cachedDomain.has(domainName)){
        this.cachedDomain.add(domainName)
        this.updateLeafNode({
          caseDomainList: this.tableData, 
          checkType: data.type, 
          checkValue: data.label,
          callback: () => {
            setTimeout( () => {
              this.treeChecked = this.$refs.tree.getCheckedKeys(true)
            }, 0)
            
          }
        })
      } else {
        this.treeChecked = this.$refs.tree.getCheckedKeys(true)
      }
    },
    tableSelect(selection, row) {
      // 1. 先判断是选中还是取消选中
      let isSelect = false

      if(selection.length > 0){
        for(const select of selection){
          if(select.caseUuid === row.caseUuid){
            isSelect = true
          }
        }
      }

      // 2. 是否叶子节点有加载
      if(!this.cachedDomain.has(row.caseDomain)){

        this.cachedDomain.add(row.caseDomain)
        this.updateLeafNode({
          caseDomainList: this.tableData,
          callback: () => {
            this.$refs.tree.setChecked(row.caseUuid, isSelect, false)
            this.treeChecked = this.$refs.tree.getCheckedKeys(true)
          }
        })
      } else {
        this.$refs.tree.setChecked(row.caseUuid, isSelect, false)
        this.treeChecked = this.$refs.tree.getCheckedKeys(true)
      }
    },
    tableSelectAll(selection) {
      let isSelect = false
      // 全选
      if(selection.length > 0){
        isSelect = true
      } else {
        selection = this.tableData
      }

      for(const row of selection){
        // 1. 是否叶子节点有加载
        if(!this.cachedDomain.has(row.caseDomain)){

          this.cachedDomain.add(row.caseDomain)
          this.updateLeafNode({
            caseDomainList: this.tableData,
            callback: () => {
              this.$refs.tree.setChecked(row.caseUuid, isSelect, false)
              this.treeChecked = this.$refs.tree.getCheckedKeys(true)
            }
          })
        } else {
          this.$refs.tree.setChecked(row.caseUuid, isSelect, false)
          this.treeChecked = this.$refs.tree.getCheckedKeys(true)
        }
      }
    },
    tableSelectionChange(selection) {

    },
    /**
     * 更新叶子节点 - caseDomainList
     * checkType: caseDomain, caseModule, secondeModule, case
     * caseUuid: checkType(case): 需要填此字段
     */
    updateLeafNode({caseDomainList, checkType, checkValue, callback = () => {}}) {
        const leafMap = {} // id: caseArray
        const checkedKeys = []
        const NodeCase = function(id, label) {
          this.id = id
          this.type = 'case'
          this.label = label
        }

        for (const columnData of caseDomainList) {
          // 遍历caseDomain
          for (const Node of this.treeData) {
            if(Node.label === columnData.caseDomain) {
              // 遍历caseModule
              for(const NodeModlue of Node.children){
                if(NodeModlue.label === columnData.caseModule) {
                  // 遍历secondModule
                  for(const NodeSecond of NodeModlue.children){
                    if(NodeSecond.label === columnData.secondModule) {
                      // secondModule业务处理
                      if(!leafMap[NodeSecond.id]){
                        leafMap[NodeSecond.id] = [new NodeCase(columnData.caseUuid, columnData.caseNo)]
                      }else{
                        leafMap[NodeSecond.id].push(new NodeCase(columnData.caseUuid, columnData.caseNo))
                      }

                      // 需要选择的叶子节点id
                      if(columnData[checkType] === checkValue && checkValue !== undefined){
                        checkedKeys.push(columnData.caseUuid)
                      }
                    }
                  }
                }
              }
            }
          }
        }

        // 叶子结点添加
        for(const key in leafMap){
          this.$refs.tree.updateKeyChildren(key, leafMap[key])
        }

        // checkedKeys
        if(checkedKeys.length > 0){
          setTimeout(() => {
            this.$refs.tree.setCheckedKeys(checkedKeys)
          }, 0)
        }

        callback && callback()
        // console.log(this.treeData)
    }
  }
}
</script>

